package com.xyy.saas.payment.callback.core.handler;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.jddglobal.open.client.DefaultSpiJddClient;
import com.xyy.saas.payment.adpater.jd.common.JDConstants;
import com.xyy.saas.payment.adpater.jdCredit.enums.JdCreditPayStatusEnum;
import com.xyy.saas.payment.adpater.jdCredit.req.FinanceResultNotifyReq;
import com.xyy.saas.payment.adpater.jdCredit.service.JdCreditService;
import com.xyy.saas.payment.adpater.jdCredit.support.JdCreditClientFactory;
import com.xyy.saas.payment.adpater.pingxx.domain.PayDO;
import com.xyy.saas.payment.callback.core.dto.CallbackMsg;
import com.xyy.saas.payment.callback.core.result.CallbackRunner;
import com.xyy.saas.payment.common.Constants;
import com.xyy.saas.payment.common.RocketMqTopic;
import com.xyy.saas.payment.common.exception.PaymentException;
import com.xyy.saas.payment.cores.enums.ResultCodeEnum;
import com.xyy.saas.payment.cores.vo.CallbackResultVo;
import com.xyy.saas.payment.dao.mapper.PrePayOrderMapper;
import com.xyy.saas.payment.dao.model.PayResultOrder;
import com.xyy.saas.payment.dao.model.PrePayOrder;
import com.xyy.saas.payment.payment.core.service.PrePayOrderService;
import com.xyy.saas.payment.service.PayResultOrderService;
import com.xyy.saas.payment.util.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.Objects;

/**
 * 京东融资支付结果通知
 */
@Component
@Slf4j
public class JdCreditPayResultHandler {

    @Autowired
    private JdCreditService jdCreditService;
    @Autowired
    private PrePayOrderMapper prePayOrderMapper;
    @Autowired
    private CallbackRunner callbackRunner;
    @Resource
    private SkyWalkingMonitorUtil skyWalkingMonitorUtil;
    @Autowired
    private PayResultOrderService payResultOrderService;
    @Autowired
    private PrePayOrderService prePayOrderService;
    @Resource
    private RedisUtil redisUtil;
    public String callBackHandler(HttpServletRequest request) throws Exception {

        DefaultSpiJddClient defaultSpiJddClient = JdCreditClientFactory.getDefaultSpiJddClient();
        String bizContent = defaultSpiJddClient.receive(request);
        log.info("bizContent={}", bizContent);
        FinanceResultNotifyReq jdNotifyTradeVo = JSON.parseObject(bizContent, FinanceResultNotifyReq.class);
        log.info("financeResultNotifyReq={}", JSONObject.toJSONString(jdNotifyTradeVo));

        if (!jdNotifyTradeVo.checkParam()) {
            throw new PaymentException(ResultCodeEnum.PARAM_ERROR);
        }

        String key = RedisUtil.JD_CREDIT_PAY_NOTIFY + jdNotifyTradeVo.getOrderCode();
        if(!redisUtil.setNx(key,"1",10)) {
            throw new PaymentException(ResultCodeEnum.PROFIT_SHARING_REPEAT_REQUEST);
        }
        /**
         * 业务方逻辑处理...
         */

        // 查询预支付订单
        PrePayOrder prePayOrder = prePayOrderService.getPrePayOrderByPayNo(jdNotifyTradeVo.getOrderCode());
        if(prePayOrder == null) {
            log.error("JdCreditPayResultHandler#callBackHandler order not exit error orderNo:{}", jdNotifyTradeVo.getOrderCode());
            throw new PaymentException(ResultCodeEnum.PARAM_ERROR,"未查到预支付单");
        }
        //支付失败直接通知业务方
        if (!JDConstants.JD_CREDIT_SUCCESS_CODE.equals(jdNotifyTradeVo.getResCode())) {
            // 异步回调业务
            String topic = getPaySuccessNotifyTopic(prePayOrder.getBusinessType(), prePayOrder.getBusinessOrderType());

            CallbackMsg callbackMsg = new CallbackMsg();
            callbackMsg.setTradeNo(prePayOrder.getPayNo());
            callbackMsg.setType(CallbackResultVo.PAY_FAIL);
            callbackMsg.setAmount(prePayOrder.getAmount());
            callbackMsg.setCallback(prePayOrder.getCallbackAddress());
            callbackMsg.setNotifyTime(DateUtil.now());
            callbackRunner.callback(topic, callbackMsg);
            return "";
        }

        // 幂等判断
        PayResultOrder payResultOrder = payResultOrderService.selectByPayNoAndChannel(jdNotifyTradeVo.getOrderCode(), "jd_credit");

        if(payResultOrder != null) {
            log.error("jd credit pay callback repeat payNo:{}", jdNotifyTradeVo.getOrderCode());
//            throw new PaymentException(ResultCodeEnum.REQUEST_PROCESSED);
            return "";
        }

        JSONObject extra = (StringUtils.isBlank(prePayOrder.getExtra()) ? new JSONObject() : JSONObject.parseObject(prePayOrder.getExtra()));
        // 基本参数
        PayDO payDO = new PayDO();
        payDO.setOrderNo(jdNotifyTradeVo.getOrderCode());
//        payDO.setChannelChargeNo(jdNotifyTradeVo.getLoanNo());
        payDO.setAmount(AmountCastUtil.castYuan2Fen(jdNotifyTradeVo.getPayAmount()));
        payDO.setChannel(Constants.CHANNEL_JD_CREDIT);
        payDO.setPayMode(extra.getString("payMode"));
        payDO.setResultCode(transTradeStatus(jdNotifyTradeVo.getApplyStatus()));
        payDO.setChannelTransactionNo(jdNotifyTradeVo.getLoanNo());
        payDO.setTimePaid(StringUtils.isBlank(jdNotifyTradeVo.getPayDate()) ? null : DateUtil.parase(jdNotifyTradeVo.getPayDate(), DateUtil.YYYYMMDDHHMMSS));
        payDO.setFailureMsg(jdNotifyTradeVo.getResDesc());
        // 其他参数
        payDO.setNotifyTime(DateUtil.now());
        payDO.setCount(0);
        payDO.setExtra(prePayOrder.getExtra());
        payDO.setBusinessType(prePayOrder.getBusinessType());
        payDO.setBusinessOrderType(prePayOrder.getBusinessOrderType());
        payDO.setReceiverId(prePayOrder.getReceiverId());
        payDO.setCallbackAddress(prePayOrder.getCallbackAddress());
        payDO.setPayer(prePayOrder.getPayer());

        Date startTime = DateUtil.now();
        payDO.setNotifyTime(DateUtil.now());

        // 检验订单金额
        if(!payDO.getAmount().equals(prePayOrder.getAmount())) {
            // 回调进来的金额和发起订单金额不等
            log.error("JdCreditPayResultHandler#callBackHandler callback amount error  payDo:{} pay:{}", JSON.toJSONString(payDO), JSON.toJSONString(prePayOrder));
            throw new PaymentException(ResultCodeEnum.PARAM_ERROR);
        }


        payDO.setBusinessType(prePayOrder.getBusinessType());
        payDO.setBusinessOrderType(prePayOrder.getBusinessOrderType());
        payDO.setReceiverId(prePayOrder.getReceiverId());
        payDO.setCallbackAddress(prePayOrder.getCallbackAddress());
        payDO.setPayer(prePayOrder.getPayer());
        payDO.setCount(0);
        callbackRunner.callbackPingXX(payDO);
        return "";
    }
    private String getPaySuccessNotifyTopic(String businessType, String businessOrderType) {
        try {
            // 1.根据产品线获取topic
            String topic = ApolloUtil.getProperty("paySuccess_notify_topic_" + businessOrderType);

            if(!StringUtils.isBlank(topic)) {
                return topic;
            }

            // 2.根据业务线获取topic
            topic = ApolloUtil.getProperty("paySuccess_notify_topic_" + businessType);

            if(!StringUtils.isBlank(topic)) {
                return topic;
            }
        }
        catch(Exception ex) {
            log.error(ex.getMessage(), ex);
        }

        return RocketMqTopic.TOPIC_CALLBACK;
    }
    /**
     * 转换交易状态
     */
    public static String transTradeStatus(String tradeStatus) throws PaymentException {
        if (tradeStatus.equals(JdCreditPayStatusEnum.PAID.getCode())) {
            return "SUCCESS";
        } else if (tradeStatus.equals(JdCreditPayStatusEnum.FAIL.getCode())) {
            return "FAIL";
        }
        throw new PaymentException(ResultCodeEnum.DEFAULT_ERROR, "交易状态错误");
    }

}
